package torres.map;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Scanner;

import torres.action.Effect;
import torres.entity.Entity;
import torres.entity.NPC;
import torres.entity.Occupation;
import torres.entity.Smasher;
import torres.entity.Sneak;
import torres.entity.Summoner;
import torres.map.terrain.*;
import torres.map.decal.*;
import torres.map.areaeffect.*;

/**
 * @author Torres
 * Generates a two dimensional array of tiles which can be used to instantiate
 * a Map object.
 */
public class MapGenerator {
	
	/**
	 * Creates a Tile[][] that is a representation of the specified .map file.
	 * @param file The .map file from which the Tile[][] is being generated.
	 * @return The Tile[][] that is a representation of the specified .map file.
	 */
	public static Tile[][] generate(File file) {
		
		Scanner reader = null;
		Tile tiles[][] = null;
		
		try{
			reader = new Scanner(file);
			int row = reader.nextInt();
			int column = reader.nextInt();
			tiles = new Tile[row][column];
			
			//parse the map file for each tile's terrain type
			int line = 0;
			while(line < row) {
				for(int col = 0; col < column; col++) {
					
					char c = reader.next().toUpperCase().charAt(0);
					switch(c) {
					
						case 'G':
							tiles[line][col] = new Tile();
							tiles[line][col].setTerrain(Grass.getInstance());
							break;
						case 'M':
							tiles[line][col] = new Tile();
							tiles[line][col].setTerrain(Mountain.getInstance());
							break;
						case 'W':
							tiles[line][col] = new Tile();
							tiles[line][col].setTerrain(Water.getInstance());
							break;
						case 'F':
							tiles[line][col] = new Tile();
							tiles[line][col].setTerrain(DojoFloor.getInstance());
							break;
						case 'D':
							tiles[line][col] = new Tile();
							tiles[line][col].setTerrain(DojoWall.getInstance());
							break;
						default:
							System.out.println("BAD, BAD, BAD....");
					}
				}
				line++;
			}
			reader.next();
			
			line = 0;
			while(line < row) {
				for(int col = 0; col < column; col++) {
					
					char c = reader.next().toUpperCase().charAt(0);
					switch(c) {
					
						case 'H':
							tiles[line][col].setDecal(RedCross.getInstance());
							tiles[line][col].setAreaEffect(new HealDamage());
							break;
						case 'P':
							tiles[line][col].setDecal(Biohazard.getInstance());
							tiles[line][col].setAreaEffect(new TakeDamage());
							break;
						case 'D':
							tiles[line][col].setDecal(SkullCrossbones.getInstance());
							tiles[line][col].setAreaEffect(new InstantDeath());
							break;
						case 'L':
							tiles[line][col].setDecal(GoldStar.getInstance());
							tiles[line][col].setAreaEffect(new LevelUp());
							break;
					}
				}
				line++;
			}
			reader.next();
			
			//parse the map file for any teleporters
			while(reader.hasNext()) {
				
				String mapName = reader.next();
				int fromX = reader.nextInt();
				int fromY = reader.nextInt();
				int toX = reader.nextInt();
				int toY = reader.nextInt();
				
				Teleport teleporter = new Teleport(mapName, new Location(toX, toY));
				tiles[fromY][fromX].setAreaEffect(teleporter);
				tiles[fromY][fromX].setDecal(Portal.getInstance());
			}
			
			return tiles;
		}
		catch(Exception e) {
			e.printStackTrace();
			System.out.println(e.toString() + "-> Scream!!!!" );
		}
		finally {
			reader.close();
		}
		return tiles;
	}
	
	/**
	 * @param map the map to generate the enemies on
	 * @param file the enemy file
	 */
	public static void generateEnemies(Map map, File file) {
		try {
			Scanner in = new Scanner(file);
			Collection<Entity> enemies = new ArrayList<Entity>();
			in.nextLine(); in.nextLine(); in.nextLine(); //throw away the template and ""
			
			String name;
			String imageName;
			Occupation job;
			int intellect;
			int strength;
			int agility;
			int hardiness;
			int movement; 
			int level;
			int bindWound;
			int bargain;
			int observation;
			int influenceRadius;
			int fireResistance;
			int waterResistance;
			int airResistance;
			int lightningResistance;
		//	Location location;
			Effect elementType;
			String aiType;
			while(in.hasNext()) {
				name = in.next();
				imageName  = in.next();
				String jobString = in.next().toLowerCase();
				if(jobString.equals("smasher"))
					job = new Smasher();
				else if(jobString.equals("sneak"))
					job = new Sneak();
				else if(jobString.equals("summoner"))
					job = new Summoner();
				else
					throw new RuntimeException("Invalid Occupation");
				intellect = in.nextInt(); 
				strength = in.nextInt();
				agility = in.nextInt();
				hardiness = in.nextInt();
				movement = in.nextInt();
				level = in.nextInt();
				bindWound = in.nextInt();
				bargain = in.nextInt();
				observation = in.nextInt();
				influenceRadius = in.nextInt();
				fireResistance = in.nextInt();
				waterResistance = in.nextInt();
				airResistance = in.nextInt();
				lightningResistance = in.nextInt();
				String word = in.next();
				word = word.substring(1,word.length()-1);
				String[] data = word.split(",");
				Location loc = new Location(Integer.parseInt(data[0]), Integer.parseInt(data[1]));
				elementType = Effect.valueOf(in.next().toUpperCase());
				aiType = in.next();
				NPC npc = new NPC(name, imageName, aiType, job, intellect, strength, agility, hardiness, movement, level, bindWound,
						bargain, observation, influenceRadius, fireResistance, waterResistance, airResistance, 
						lightningResistance, loc, elementType);
				
				enemies.add(npc);
				map.registerEnemyAI(aiType, npc);
				map.addEntity(npc, loc);
			}
			map.setEnemies(enemies);
			
		}
		catch(FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}
	
}